
#pragma once
#include <iostream>
#include "Mutex.hpp"
#include "Cond.hpp"
#include <queue>

using namespace MyCond;
using namespace MyMutex;

const int defaultcap = 5;
template <typename T>
class BlockQueue
{
private:
    bool IsFull() { return _bq.size() >= _cap; }
    bool IsEmpty() { return _bq.empty(); }

public:
    BlockQueue(const int cap = defaultcap)
        : _cap(cap),
          _p_sleep_num(0),
          _c_sleep_num(0)
    {
    }

    void Equeue(const T &data) // 生产者:入数据
    {
        {
            LockGuard lg(&_mutex);
            while (IsFull()) // 队列满了
            {
                _p_sleep_num++;
                printf("生产者休眠：%d\n", _p_sleep_num);
                _producer_cond.Wait(_mutex); // 在条件变量里等
                _p_sleep_num--;
            }
            // 队列还有空间
            _bq.push(data); // 入数据

            if (_c_sleep_num > 0) // 如果有消费者线程在休眠
            {
                _consumer_cond.Signal(); // 唤醒一个消费者
                std::cout << "唤醒消费者..." << std::endl;
            }
        }
    }

    T Pop() // 消费者：拿数据
    {
        T data;
        {
            LockGuard lg(&_mutex);
            while (IsEmpty()) // 队列里没东西
            {
                _c_sleep_num++;
                _consumer_cond.Wait(_mutex); // 在条件变量里等
                _c_sleep_num--;
            }
            // 队列里还有数据
            data = _bq.front(); // 拿数据
            _bq.pop();

            if (_p_sleep_num > 0) // 如果有生产者线程在休眠
            {
                _producer_cond.Signal(); // 唤醒一个生产者
                std::cout << "唤醒生产者..." << std::endl;
            }
        }
        return data;
    }

    ~BlockQueue()
    {
    }

private:
    std::queue<T> _bq;   // 队列
    int _cap;            // 队列的容量
    Mutex _mutex;        // 互斥锁
    Cond _producer_cond; // 生产者的条件变量
    Cond _consumer_cond; // 消费者的条件变量
    int _p_sleep_num;    // 生产者休眠数量
    int _c_sleep_num;    // 消费者休眠数量
};

//////////////////////////////////库里的mutex和cond//////////////////////////////////
// #pragma once
// #include <iostream>
// #include <pthread.h>
// #include <queue>

// const int defaultcap = 5;
// template <typename T>
// class BlockQueue
// {
// private:
//     bool IsFull() { return _bq.size() >= _cap; }
//     bool IsEmpty() { return _bq.empty(); }

// public:
//     BlockQueue(const int cap = defaultcap)
//         : _cap(cap),
//           _p_sleep_num(0),
//           _c_sleep_num(0)
//     {
//         pthread_mutex_init(&_mutex, nullptr);
//         pthread_cond_init(&_producer_cond, nullptr);
//         pthread_cond_init(&_consumer_cond, nullptr);
//     }

//     void Equeue(const T &data) // 生产者:入数据
//     {
//         pthread_mutex_lock(&_mutex); // 加锁
//         while (IsFull())             // 队列满了
//         {
//             _p_sleep_num++;
//             printf("生产者休眠：%d\n", _p_sleep_num);
//             pthread_cond_wait(&_producer_cond, &_mutex); // 在条件变量里等
//             _p_sleep_num--;
//         }
//         // 队列还有空间
//         _bq.push(data); // 入数据

//         if (_c_sleep_num > 0) // 如果有消费者线程在休眠
//         {
//             pthread_cond_signal(&_consumer_cond); // 唤醒一个消费者
//             std::cout << "唤醒消费者..." << std::endl;
//         }

//         pthread_mutex_unlock(&_mutex); // 解锁
//     }

//     T Pop() // 消费者：拿数据
//     {
//         pthread_mutex_lock(&_mutex); // 加锁
//         while (IsEmpty())            // 队列里没东西
//         {
//             _c_sleep_num++;
//             pthread_cond_wait(&_consumer_cond, &_mutex); // 在条件变量里等
//             _c_sleep_num--;
//         }
//         // 队列里还有数据
//         T data = _bq.front(); // 拿数据
//         _bq.pop();

//         if (_p_sleep_num > 0) // 如果有生产者线程在休眠
//         {
//             pthread_cond_signal(&_producer_cond); // 唤醒一个生产者
//             std::cout << "唤醒生产者..." << std::endl;
//         }

//         pthread_mutex_unlock(&_mutex); // 解锁
//         return data;
//     }

//     ~BlockQueue()
//     {
//         pthread_mutex_destroy(&_mutex);
//         pthread_cond_destroy(&_producer_cond);
//         pthread_cond_destroy(&_consumer_cond);
//     }

// private:
//     std::queue<T> _bq;             // 队列
//     int _cap;                      // 队列的容量
//      _mutex;        // 互斥锁
//     pthread_cond_t _producer_cond; // 生产者的条件变量
//     pthread_cond_t _consumer_cond; // 消费者的条件变量
//     int _p_sleep_num;              // 生产者休眠数量
//     int _c_sleep_num;              // 消费者休眠数量
// };
